﻿define([
    'Wjs/ui/messageBox'
],
function () {
    'use strict';

    // The selector manages the selection of the container view (grid, list, tree, etc)
    return Wjs.defineOnce({

        type: 'GeoCoder',

        internal: {

            initialize: function (cfg) {

                this.geoCoder = new google.maps.Geocoder();
            }
        },

        // What to execute on success
        onSuccess: function (fcn) {

            this.successHandler = Wjs.chain(this.successHandler, fcn);

            return this;
        },

        // Error handler
        onError: function (fcn) {

            this.errorHandler = Wjs.chain(this.errorHandler, fcn);

            return this;
        },

        // What to execute when the requeste is completed (either with success or error)
        onComplete: function (fcn) {

            this.completeHandler = Wjs.chain(this.completeHandler, fcn);

            return this;
        },

        // Populates the address according to the results of the request
        populatePosition: function (results) {
            var location = results[0].geometry.location;

            return {
                latitude: location.lat(),
                longitude: location.lng()
            };
        },

        // Populates the address according to the results of the request
        populateAddress: function (results) {
            var address = {},
                parts;

            if (results[0]) {

                parts = results[0].address_components;

                parts.forEach(function (part) {

                    switch (part.types[0]) {
                        case 'postal_code':
                            {
                                address.postalCode = part.short_name;
                            }
                            break;
                        case 'country':
                            {
                                address.country = part.short_name;
                            }
                            break;
                        case 'administrative_area_level_1':
                            {
                                address.stateOrProvince = part.short_name;
                            }
                            break;
                        case 'administrative_area_level_2':
                            {
                                address.countyOrRegion = part.short_name;
                            }
                            break;
                        case 'locality':
                            {
                                address.cityOrLocality = part.short_name;
                            }
                            break;
                        case 'route':
                            {
                                address.streetOrRoute = part.short_name;
                            }
                            break;
                        case 'street_number':
                            {
                                address.streetNumber = part.short_name;
                            }
                            break;
                        case 'postal_code_suffix':
                            {
                                address.postalCodeSuffix = part.short_name;
                            }
                            break;
                        case 'establishment':
                            {
                                address.establishment = part.short_name;
                            }
                            break;
                        case 'neighborhood':
                            {
                                address.neighborhood = part.short_name;
                            }
                            break;       
                        default:
                            {
                                console.log('Unknown part type: ' + part.types[0]);
                            }
                            break;
                    }

                });

                return address;
            }

            return null; // Not found
        },

        // Internal helper to wrap the functiona
        geoCode: function (cfg, reverse) {
            var me = this;

            this.geoCoder.geocode(cfg,
                function (results, status) {
                    var data;

                    if (status == google.maps.GeocoderStatus.OK) {

                        if (reverse) { // Populate the address (from the position)

                            data = me.populateAddress(results);
                            
                        }
                        else { // Populate the position with latitude and longitude (from the address)

                            data = me.populatePosition(results);
                        }

                        if (data) {

                            me.successHandler(data);
                        }
                        else {

                            Wjs.alert()
                                .setTitle('Error')
                                .setContent('No results found')
                                .show();
                        }
                    }
                    else {

                        if (me.errorHandler) {

                            me.errorHandler(status);
                        }
                        else { // Default error handling

                            Wjs.alert()
                                .setTitle('Error')
                                .setContent(status)
                                .show();
                        }
                    }

                    if (me.completeHandler) {

                        me.completeHandler();
                    }
                },
                function () {

                    if (me.errorHandler) {

                        me.errorHandler(null);
                    }
                    else { // Default error handling

                        Wjs.alert()
                            .setTitle('Error')
                            .setContent('The Geolocation service failed.')
                            .show();
                    }

                    if (me.completeHandler) {

                        me.completeHandler();
                    }
                });
        },

        code: function (address) {

            this.geoCode({ 'address': address }, false);
        },

        reverse: function (latitude, longitude) {
            var latlng = new google.maps.LatLng(latitude, longitude);

            this.geoCode({ 'latLng': latlng }, true);
        },

        reversePostalCode: function (country,postalCode) {
            var me = this;

            // Create a geo coder to get the position based on the postal code
            var geoCoder = Wjs.new('GeoCoder')
                                .onSuccess(function (position) {

                                    me.geoCode({ latLng: new google.maps.LatLng(position.latitude, position.longitude) }, true);
                                })
                                .onError(me.errorHandler);

            geoCoder.geoCode({
                componentRestrictions: {
                    country: country,
                    postalCode: postalCode
                }
            },
            false); // Reverse
        }

    });

});